#include <stdio.h>          // 标准输入输出
#include <unistd.h>         // POSIX标准接口
#include <errno.h>          // 错误码
#include <string.h>         // 字符串处理(操作字符数组)

#include "lwip/sockets.h"   // lwIP TCP/IP协议栈：Socket API
#include <sys/types.h>

#include "udp_client.h"
// #include "ssd1306.h"        // OLED驱动接口

/// @brief UDP客户端测试函数
/// @param host UDP服务端IP地址
/// @param port UDP服务端端口
/// @param msg  UDP需要发送的信息
void UdpClientTest(const char *host, unsigned short port,char *msg )
{

// 1.创建udp
    int sock_fd;
    int ret;
    sock_fd = socket(AF_INET, SOCK_DGRAM, 0); //SOCK_DGRAM：UDP类型的socket
    if (sock_fd < 0)
    {
        perror("sock_fd create error\r\n");
        return;
    }

    // 2.配置地址
    struct sockaddr_in send_addr;
    // sockaddr_in send_addr;
    socklen_t send_addr_len = sizeof(send_addr);
    //内存初始化
    memset((void *)&send_addr, 0, send_addr_len);
    send_addr.sin_family = AF_INET;

    send_addr.sin_addr.s_addr = inet_addr(host); // 是将一个点分十进制的IP转换成一个长整数型数（u_long类型）
    send_addr.sin_port = htons(port);                       // 端口号，从主机字节序转为网络字节序
    // 3.配置发送消息
    // char *msg = "hello world";

    while (1)
    {
        //4.发送
        // UDP socket 是 “无连接的” ，因此每次发送都必须先指定目标主机和端口，主机可以是多播地址
        ret = sendto(sock_fd, msg, strlen(msg), 0, (struct sockaddr *)&send_addr, send_addr_len);
        printf("send UDP message {%s}done!\r\n", msg);
        usleep(1 * 1000 * 1000);

        // 5.接收
        // struct sockaddr_in fromAddr = {0};
        // socklen_t fromLen = sizeof(fromAddr);
        // // UDP socket 是 “无连接的” ，因此每次接收时前并不知道消息来自何处，通过 fromAddr 参数可以得到发送方的信息（主机、端口号）
        // ret = recvfrom(sock_fd, &response, sizeof(response), 0, (struct sockaddr *)&fromAddr, &fromLen);
        // if (ret <= 0)
        // {
        //     printf("recvfrom failed or abort, %ld!\r\n", ret);
        // }
        // response[ret] = '\0';
        // printf("recv UDP message {%s} %ld done!\r\n", response, ret);
        // printf("peer info: ipaddr = %s, port = %d\r\n", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port)); //将网络地址转换成“.”点隔的字符串格式。将一个16位数由网络字节顺序转换为主机字节顺序
    }
    // lwip_close(sock_fd);
}

static int sock_fd;
static struct sockaddr_in send_addr ;
static socklen_t send_addr_len ;
/**
 * @brief 初始化UDPSocket
 * @param host  UDP的目标主机
 * @param port  UDP的目标端口
*/
void inotUdpClient(const char *host, unsigned short port){
    sock_fd = socket(AF_INET, SOCK_DGRAM, 0); //SOCK_DGRAM：UDP类型的socket

    if (sock_fd < 0){
        perror("sock_fd create error\r\n");
        return;
    }

    // 2.配置地址
    // sockaddr_in send_addr;
    send_addr_len = sizeof(send_addr);
    //内存初始化
    memset((void *)&send_addr, 0, send_addr_len);
    send_addr.sin_family = AF_INET;

    send_addr.sin_addr.s_addr = inet_addr(host); // 是将一个点分十进制的IP转换成一个长整数型数（u_long类型）
    send_addr.sin_port = htons(port);                       // 端口号，从主机字节序转为网络字节序

}
/**
 * @brief 发送UDP信息
 * @param msg  UDP需要发送的信息
*/
int SendUdpInfo(char *msg){
    
    int ret;
    ret = sendto(sock_fd, msg, strlen(msg), 0, (struct sockaddr *)&send_addr, send_addr_len);
    printf("send UDP message {%s}done!\r\n", msg);

    return ret;
}


/*
 * @brief 断开udp链接
*/
void closeUdpClient(){

    lwip_close(sock_fd);

}